package ru.alt22.visor.php.unittests.run;

import java.io.InputStreamReader;
import java.io.StringReader;

import org.eclipse.core.resources.IProject;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Unmarshaller;

import ru.alt22.visor.php.core.PDToolsCorePlugin;
import ru.alt22.visor.php.properties.Properties;
import ru.alt22.visor.php.unittests.PDToolsTestsPlugin;
import ru.alt22.visor.php.unittests.core.PHPProxy;
import ru.alt22.visor.php.unittests.core.PHPTestCase;
import ru.alt22.visor.php.unittests.core.PHPTestCaseResult;

public class DefaultPHPProxy implements PHPProxy {

	private static Mapping mapping = null;
	private static Unmarshaller unmarshaller = null;
	
	static {
		try {
			mapping = new Mapping();
			mapping.loadMapping(PDToolsCorePlugin.getResource(PDToolsTestsPlugin.PLUGIN_ID, "mapping.xml"));
			unmarshaller = new Unmarshaller(mapping);
		} catch (Exception e) {
			mapping = null;
			unmarshaller = null;
			PDToolsCorePlugin.log(e);
		}
	}

	public DefaultPHPProxy() {
	}

	public PHPTestCaseResult executeTestCase(PHPTestCase test) {
		PHPTestCaseResult result = new PHPTestCaseResult();

		try {
			StringReader reader = sendToPHP(test);
			result = (PHPTestCaseResult)unmarshaller.unmarshal(reader);
		} catch (Exception e) {
			result = PHPTestCaseResult.error(e);
		}

		return result;
	}

	private StringReader sendToPHP(PHPTestCase test) throws Exception {
		IProject project = test.getReflectionClass().getProject();

		String phpExe = Properties.getPHPExecutable(project);
		String script = Properties.getTestScript(project);
		if (phpExe == null || script == null) {
			throw new Exception("No PHP Tests settings specified for project " + project.getName());
		}

		Process process = Runtime.getRuntime().exec(new String[] {
			phpExe,
			"-q",
			project.getFile(script).getLocation().toString(),
			test.getClassName(),
			test.getName()
		});

		InputStreamReader stdout = new InputStreamReader(process.getInputStream());

		StringBuffer buffer = new StringBuffer();
		char[] line = new char[4096];
		int length;
		do {
			length = stdout.read(line);
			if (length < 0) {
				break;
			}
			buffer.append(line, 0, length);
		} while (0 != length);
		process.destroy();
		process = null;

		return new StringReader(buffer.toString());
	}

}